/* eslint-disable */
import { message, notification } from 'antd';
import memoryUtils from '@/utils/memoryUtils';

import { CORE_JAR_PREFIX, HOST_IP, LEASE_HOURS } from '@/utils/constants';

// import './baja.js';

const bajaPromise = window.bajaPromise;
const alarmPromise = window.alarmPromise;

const Baja = () => {
  if (!bajaPromise) {
    message.error('Baja() 全局bajaPromise为空');
    return null;
  }
  return new Promise((resolve) => {
    bajaPromise.then(baja => {
      memoryUtils.user.username = baja.getUserName();
      resolve(baja);
    }).catch(error => {
      message.error('Baja() error：' + error.message);
    });
  });
};

const makeOrd = (baja, ord) => {
  return new Promise((resolve) => {
    baja.Ord.make(ord).get({
      lease: true, // Temporarily subscribe the Counter for one minute.
      leaseTime: baja.RelTime.make({ hours: LEASE_HOURS }),
    }).then(component => {
      resolve(component);
    }).catch(error => {
      message.error('makeOrd() error: ' + error.message);
    });
  });
};

const Ord = async (ord) => {
  // console.log("Ord", ord);
  const baja = await Baja();
  if (baja) {
    const component = await makeOrd(baja, ord);
    return Promise.resolve(component);
  } else {
    message.error('Ord(): baja 获取失败');
  }
};

const makeBqlSearch = (baja, bql, column) => {
  return new Promise((resolve) => {
    const results = [];
    baja.Ord.make(bql).get({
      cursor: {
        each: function() {
          results.push(this.get(column));
        },
        after: function() {
          resolve(results);
        },
        limit: 1000, // Specify optional limit on the number of records (defaults to 10)
      },
    }).then(result => {
      console.log('makeBqlSearch result', result);
    }).catch(error => {
      message.error('makeBqlSearch() error：' + error.message + ', ' + bql);
    });
  });
};

const BqlSearch = async (bql, column) => {
  const baja = await Baja();
  if (baja) {
    const results = await makeBqlSearch(baja, bql, column);
    return Promise.resolve(results);
  } else {
    message.error('bqlSearch(): baja fetch failure!');
  }
};

const initHnxWebService = async () => {
  const hnxWebService = await Ord('station:|slot:/Services/HnxWebService'); //station:|slot:/Services/HnxWebService
  memoryUtils.hnxWebService = hnxWebService;
  return Promise.resolve(hnxWebService);
};

const fetchHnxWebService = () => {
  const hnxWebService = memoryUtils.hnxWebService;
  if (hnxWebService && hnxWebService.$parent) {
    return hnxWebService;
  } else {
    return initHnxWebService();
  }
};

const findSubSystemFromTypeSpec = (subSystems, subSystemTypeSpec) => {
  let subSystem = null;
  if(subSystems && subSystems.length > 0 && subSystemTypeSpec) {
    for(let i=0; i<subSystems.length; i++) {
      if(subSystems[i].children && subSystems[i].children.length > 0) {
        const node = findSubSystemFromTypeSpec(subSystems[i].children, subSystemTypeSpec);
        if(node && node.$typeSpec.endsWith(subSystemTypeSpec) ||
          (node && node.subSystemType === 'PAGE' && node.pagePath.toLowerCase()==='/'+subSystemTypeSpec.toLowerCase())) {
          subSystem = node;
          break;
        }
      } else if(subSystems[i].$typeSpec.endsWith(subSystemTypeSpec) ||
        (subSystems[i].subSystemType === 'PAGE'&&subSystems[i].pagePath.toLowerCase()==='/'+subSystemTypeSpec.toLowerCase())) {
        subSystem = subSystems[i];
        break;
      }
    }
  }
  return subSystem;
}

const initSubSystemFromTypeSpec= async (subSystemTypeSpec) => {
  const subSystemsRoot = await Ord('station:|slot:/Services/HnxWebService/subSystemsRoot');
  let subSystems = await fetchNavChildren(subSystemsRoot);
  subSystems = await fetchSubSystems(subSystems);
  const subSystem = findSubSystemFromTypeSpec(subSystems, subSystemTypeSpec);
  if(!subSystem) {
    message.error('initSubSystemFromTypeSpec failed. not found the subSystem from ' + subSystemTypeSpec);
    return Promise.resolve({});
  }
  memoryUtils.subSystemMap[subSystemTypeSpec] = subSystem;
  return Promise.resolve(subSystem);
}

const fetchSubSystemFromTypeSpec = (subSystemTypeSpec) => {
  const subSystem = memoryUtils.subSystemMap[subSystemTypeSpec];
  if(subSystem) {
    return subSystem;
  } else {
    return initSubSystemFromTypeSpec(subSystemTypeSpec);
  }
}

const fetchNavChildren = async (component) => {
  if (!component.$lease) {
    component = await Ord('station:|h:' + component.$handle);
  }
  const kids = await component.getNavChildren();
  // console.log('fetchNavChildren() kids', kids);
  if (kids) {
    for (let i = 0; i < kids.length; i++) {
      if (!kids[i].$lease) {
        kids[i] = await Ord('station:|h:' + kids[i].$handle);
      }
    }
  }
  return Promise.resolve(kids);
};

const subscribeComp = async (ord, update) => {
  const baja = await Baja();
  const sub = new baja.Subscriber();
  sub.attach('changed', function(prop) {
    update(this, prop);
  });
  baja.Ord.make(ord).get({ subscriber: sub }).then(component => {
    update(component);
  });
  return Promise.resolve(sub);
};

const subscribeAlarm = () => {
  alarmPromise.then(async (AlarmConsoleViewModel) => {
    const consoleOrd = 'station:|slot:/Services/AlarmService/ConsoleRecipient';
    const RECIPIENT_UPDATE_EVENT = 'recipientUpdate';
    const c = await Ord(consoleOrd);
    const viewModel = new AlarmConsoleViewModel(null);
    viewModel.on(RECIPIENT_UPDATE_EVENT, function(summary, update) {
      if (update) {
        const { records } = summary;
        if (records) {
          let record = { lastUpdate: 0 };
          records.forEach(function(item) {
            if (item.lastUpdate > record.lastUpdate) {
              record = item;
            }
          });
          if (record.lastUpdate > 0) {
            const { alarmData, timestamp } = record;
            notification.warning({
              message: 'Alarm: ' + alarmData.sourceName,
              description:
                <p>Detail: {alarmData.msgText} <br/>Time: {new Date(timestamp).toLocaleString()}</p>,
              placement: 'bottomRight',
              onClick: () => {
                // router.push('/subSystemm/3779');
              },
            });
          }
        }
      }
    });
    c.lease().then(function() {
      viewModel.load(c);
    });
  }).catch(error => {
    message.error('subscribeAlarm() error：' + error.message);
  });
};

const fetchTreeMenus = async ({treeMenus, parentNode=null, mode='INLINE'}) => {
  const treeMenuList = [];
  if (treeMenus && treeMenus.length > 0) {
    for (let i = 0; i < treeMenus.length; i++) {
      const { $typeSpec } = treeMenus[i].getType();
      if ($typeSpec.endsWith('TreeMenuGroup')||$typeSpec.endsWith('EnergyArea')||$typeSpec.endsWith('EnergyCategory')) {
        if($typeSpec.endsWith('EnergyCategory') && JSON.stringify(memoryUtils.ENERGYCATEGORY_TYPE) === '{}') {
          const energyTypeExpose =  treeMenus[i].getEnergyTypeExpose();
          const obj = JSON.parse(energyTypeExpose);
          for (let key in obj) {
            memoryUtils.ENERGYCATEGORY_TYPE[obj[key]] = key;
          }
        }
        const treeMenuItems = await fetchNavChildren(treeMenus[i]);
        const node = {
          $handle: treeMenus[i].$handle,
          $typeSpec,
          title: treeMenus[i].getTitle(),
          nIcon: 'folder',
          navOrd: treeMenus[i].getNavOrd().toString(),
          key: treeMenus[i].$handle,
          parent: parentNode,
          mode,
        };
        if($typeSpec.endsWith('EnergyCategory')) {
          const { $ordinal } = treeMenus[i].getEnergyCategoryType();
          node['energyCategoryType'] = memoryUtils.ENERGYCATEGORY_TYPE[$ordinal];
        }
        node.children = await fetchTreeMenus({treeMenus:treeMenuItems, parentNode: node, mode});
        treeMenuList.push(node);
      } else if ($typeSpec.endsWith('TreeMenuItem')) {
        if (JSON.stringify(memoryUtils.TREEMENUITEM_TYPE) === '{}') {
          const treeMenuItemTypeExpose =  treeMenus[i].getTreeMenuItemTypeExpose();
          const obj = JSON.parse(treeMenuItemTypeExpose);
          for (let key in obj) {
            memoryUtils.TREEMENUITEM_TYPE[obj[key]] = key;
          }
        }
        const { $ordinal } = treeMenus[i].getTreeMenuItemType();
        const node = {
          $handle: treeMenus[i].$handle,
          $typeSpec,
          title: treeMenus[i].getTitle(),
          nIcon: treeMenus[i].getNIcon(),
          redirectToBase: treeMenus[i].getRedirectToBase(),
          baseUrl: treeMenus[i].getBaseUrl(),
          pagePath: treeMenus[i].getPagePath(),
          url: treeMenus[i].getUrl(),
          navOrd: treeMenus[i].getNavOrd().toString(),
          treeMenuItemType: memoryUtils.TREEMENUITEM_TYPE[$ordinal],
          key: treeMenus[i].$handle,
          parent: parentNode,
          mode,
        }
        if(memoryUtils.TREEMENUITEM_TYPE[$ordinal] === 'SEARCH_PARAMS') {
          // fetchSearchParamsFromOrd(treeMenus[i].getNavOrd().toString()).then((searchParams)=>{
          //   node.searchParams = searchParams;
          // });
          node.searchParams = await fetchSearchParamsFromOrd(treeMenus[i].getNavOrd().toString());
        }
        treeMenuList.push(node);
      }
    }
  }
  return Promise.resolve(treeMenuList);
};

const fetchSearchParamsFromOrd = async (treeMenuOrd) => {
  let searchParams = [];
  const treeMenuItem = await Ord(treeMenuOrd);
  if(treeMenuItem) {
    const { $ordinal } = treeMenuItem.getTreeMenuItemType();
    const treeMenuItemType = memoryUtils.TREEMENUITEM_TYPE[$ordinal];
    if(treeMenuItemType === 'SEARCH_PARAMS') {
      const navOrd = treeMenuItem.getNavOrd().toString();
      const searchParamRoot = await Ord(navOrd+'/searchParamRoot');
      if(searchParamRoot) {
        searchParams = await fetchNavChildren(searchParamRoot);
        searchParams = await fetchSearchParams(searchParams);
        if(!searchParams) {
          searchParams = []
        }
      }
    }
  }
  return searchParams;
}

const fetchSearchParams = async (searchParams, parentNode=null) => {
  const searchParamList = [];
  if (searchParams && searchParams.length > 0) {
    for (let i = 0; i < searchParams.length; i++) {
      const { $typeSpec } = searchParams[i].getType();
      if ($typeSpec.endsWith('SearchParamGroup')||$typeSpec.endsWith('EnergyArea')||$typeSpec.endsWith('EnergyCategory')) {
        const searchParamItems = await fetchNavChildren(searchParams[i]);
        const node = {
          title: searchParams[i].getTitle(),
          value: searchParams[i].$handle,
          key: searchParams[i].$handle,
          parent: parentNode,
          navOrd: searchParams[i].getNavOrd().toString(),
        };
        if($typeSpec.endsWith('EnergyCategory')) {
          const { $ordinal } = searchParams[i].getEnergyCategoryType();
          node['energyCategoryType'] = memoryUtils.ENERGYCATEGORY_TYPE[$ordinal];
          node['price'] = searchParams[i].getPrice();
        }
        node.children = await fetchSearchParams(searchParamItems, node);
        searchParamList.push(node);
      } else if($typeSpec === CORE_JAR_PREFIX + ':ExtSearchParamItem') {
        searchParamList.push({
          title: searchParams[i].getTitle(),
          value: searchParams[i].$handle,
          key: searchParams[i].$handle,
          historyOrds: searchParams[i].getHistoryOrds().$ords,
          alarmClassOrd: searchParams[i].getAlarmClassOrd().$ord,
          parent: parentNode,
          navOrd: searchParams[i].getNavOrd().toString(),
        });
      } else if ($typeSpec.endsWith('SearchParamItem')) {
        searchParamList.push({
          title: searchParams[i].getTitle(),
          value: searchParams[i].$handle,
          key: searchParams[i].$handle,
          historyOrds: [searchParams[i].getHistoryOrd().$ord],
          alarmClassOrd: searchParams[i].getAlarmClassOrd().$ord,
          parent: parentNode,
          navOrd: searchParams[i].getNavOrd().toString(),
        });
      }
    }
  }
  return Promise.resolve(searchParamList);
}

const fetchSubSystems = async (subSystems, parentNode=null) => {
  const subSystemList = [];
  if (subSystems && subSystems.length > 0) {
    for(let i=0; i<subSystems.length; i++) {
      const subSystem = subSystems[i];
      if(subSystem.getEnabled() === false) {
        continue;
      }
      const { $typeSpec } = subSystem.getType();
      if($typeSpec.endsWith('SubSystemGroup')) {
        const childrenSubSystems = await fetchNavChildren(subSystem);
        const node = {
          $handle: subSystem.$handle,
          $typeSpec,
          title: subSystem.getTitle(),
          nIcon: subSystem.getNIcon(),
          navOrd: subSystem.getNavOrd().toString(),
          parent: parentNode,
        };
        node.children = await fetchSubSystems(childrenSubSystems, node);
        subSystemList.push(node);
      } else if ($typeSpec.endsWith('SubSystem')) {
        if(JSON.stringify(memoryUtils.SUBSYSTEM_TYPE)==='{}') {
          const subSystemTypeExpose = subSystem.getSubSystemTypeExpose();
          const obj = JSON.parse(subSystemTypeExpose);
          for(let key in obj) {
            memoryUtils.SUBSYSTEM_TYPE[obj[key]] = key;
          }
        }
        const { $ordinal } = subSystem.getSubSystemType();
        const modulesRoot = await Ord(subSystem.getNavOrd().toString() + '/modulesRoot');
        subSystem.modules = [];
        if(modulesRoot) {
          const modules = await fetchNavChildren(modulesRoot);
          subSystem.modules = await fetchSubModules(modules);
        }
        subSystemList.push({
          $handle: subSystem.$handle,
          $typeSpec,
          title: subSystem.getTitle(),
          nIcon: subSystem.getNIcon(),
          lockToIndex: subSystem.getLockToIndex(),
          redirectToBase: subSystem.getRedirectToBase(),
          baseUrl: subSystem.getBaseUrl(),
          subSystemType: memoryUtils.SUBSYSTEM_TYPE[$ordinal],
          pagePath: subSystem.getPagePath(),
          url: subSystem.getUrl(),
          navOrd: subSystem.getNavOrd().toString(),
          modules: subSystem.modules,
          parent: parentNode,
        });
        // if(subSystem.getRedirectToBase()) {
        //   const url = (subSystem.getBaseUrl().startsWith("http://")||subSystem.getBaseUrl().startsWith("https://"))?subSystem.getBaseUrl():
        //     HOST_IP + '/ord/file:%5E' + subSystem.getBaseUrl();
        //   memoryUtils.subSystemHandleToUrlMap[subSystem.$handle] = 'redirect:' + url;
        // } else
        if(memoryUtils.SUBSYSTEM_TYPE[$ordinal] === 'URL') {
          const url = (subSystem.getUrl().startsWith("redirect:")||subSystem.getUrl().startsWith("http://")||subSystem.getUrl().startsWith("https://"))?subSystem.getUrl():
            HOST_IP + '/ord/file:%5E' + subSystem.getUrl();
          memoryUtils.subSystemHandleToUrlMap[subSystem.$handle] = url;
        }
      }
    }
  }
  return Promise.resolve(subSystemList);
}

const fetchSubModules = async (subModules, parentNode=null) => {
  const subModuleList = [];
  if (subModules && subModules.length > 0) {
    for(let i=0; i<subModules.length; i++) {
      const subModule = subModules[i];
      if(subModule.getEnabled() === false) {
        continue;
      }
      const { $typeSpec } = subModule.getType();
      if($typeSpec.endsWith('ModuleGroup')) {
        const childrenModules = await fetchNavChildren(subModule);
        const node = {
          $handle: subModule.$handle,
          $typeSpec,
          title: subModule.getTitle(),
          nIcon: subModule.getNIcon(),
          navOrd: subModule.getNavOrd().toString(),
          parent: parentNode,
        };
        node.children = await fetchSubModules(childrenModules, node);
        subModuleList.push(node);
      } else if ($typeSpec.endsWith('Module')) {
        if(JSON.stringify(memoryUtils.MODULE_TYPE)==='{}') {
          const moduleTypeExpose = subModule.getModuleTypeExpose();
          const obj = JSON.parse(moduleTypeExpose);
          for(let key in obj) {
            memoryUtils.MODULE_TYPE[obj[key]] = key;
          }
        }
        const { $ordinal } =  subModule.getModuleType();
        subModuleList.push({
          $handle: subModule.$handle,
          $typeSpec,
          title: subModule.getTitle(),
          nIcon: subModule.getNIcon(),
          redirectToBase: subModule.getRedirectToBase(),
          baseUrl: subModule.getBaseUrl(),
          moduleType: memoryUtils.MODULE_TYPE[$ordinal],
          pagePath: subModule.getPagePath(),
          url: subModule.getUrl(),
          navOrd: subModule.getNavOrd().toString(),
          parent: parentNode,
        });
      }
    }
  }
  return Promise.resolve(subModuleList);
}

const initEnergyCategoryPrices = async () => {
  const energySettingTreeMenuItemOrds = await BqlSearch('station:|slot:/Services/HnxWebService|bql:select navOrd from ' + CORE_JAR_PREFIX + ':EnergySettingTreeMenuItem', 'navOrd');
  if (energySettingTreeMenuItemOrds && energySettingTreeMenuItemOrds.length > 0) {
    const searchParamRoot = await Ord(energySettingTreeMenuItemOrds[0].$ord + '/searchParamRoot');
    const children = await fetchNavChildren(searchParamRoot);
    if (children) {
      return children.map(item => {
        // if(JSON.stringify(memoryUtils.ENERGYCATEGORY_TYPE)==='{}') {
        //   const energyTypeExpose = item.getEnergyTypeExpose();
        //   const obj = JSON.parse(energyTypeExpose);
        //   for(let key in obj) {
        //     memoryUtils.ENERGYCATEGORY_TYPE[obj[key]] = key;
        //   }
        // }
        // const { $ordinal } = item.getEnergyCategoryType();
        return {
          $handle: item.$handle,
          navOrd: item.getNavOrd().toString(),
          title: item.getTitle(),
          // energyCategoryType: memoryUtils.ENERGYCATEGORY_TYPE[$ordinal],
          price: item.getPrice(),
        };
      });
    }
  }
  return false;
}

const setEnergyCategoryPrice = async (navOrd, price) => {
  const energyCategory = await Ord(navOrd);
  if (energyCategory) {
    energyCategory.setPrice(price);
  }
}

export {
  Baja,
  Ord,
  BqlSearch,
  initHnxWebService,
  fetchHnxWebService,
  fetchSubSystemFromTypeSpec,
  fetchNavChildren,
  subscribeComp,
  subscribeAlarm,
  fetchTreeMenus,
  fetchSearchParamsFromOrd,
  fetchSearchParams,
  fetchSubSystems,
  fetchSubModules,
  initEnergyCategoryPrices,
  setEnergyCategoryPrice
};
